// 扩展1-2 mutable
/**
 * 参考链接: 
 * https://www.html.cn/softprog/c/130278.html
 * https://blog.csdn.net/Trouble_provider/article/details/90521215
 * 总结：
 *  1. 类成员属性使用mutable修饰，可在const函数内改变该属性
 *  2. 不能修饰static成员属性
 *  3. lambda函数定义中使用（()后面）,会使值捕获变量的值，每次调用lambda时都在其基础上改变，类似于函数体内定义static变量接收该值捕获变量的值，不会对该变量本身造成影响。
*/
#include <iostream>
#include <functional>
class Test
{
private:
  int a;
  mutable int num;

public:
  Test() : num(0) {}

  void fun1() const
  {
    std::cout << "fun1()..." << std::endl;
    std::cout << "num : " << num << std::endl;
    this->num++;
    // num++;
  }
  // 无法用auto推导
  // auto fun2 = []() -> void
  const std::function<void()> fun2 = []() -> void
  {
    std::cout << "fun2()..." << std::endl;
    // std::cout << "num : " << num << std::endl;
  };

  const std::function<void()> fun3 = [this]() -> void
  {
    // this是指针 引用调用
    std::cout << "fun3()..." << std::endl;
    std::cout << "num : " << num << std::endl;
    // num++;
    a++;
  };

  // c++17支持 *this ,我改了，运行终止程序
  /**
   * [*this]指的是按照值传递值。相当于把所有值都拷贝一遍。所以在lam函数中是无法使用this 指针的。而你是在类中定义的fun4函数。类中的函数返回值应该是在编译前指定的。除非使用模板。所以这个函数属于成员函数。所以可以使用this指针。倒是成员函数调用自己应该是this.
  */
  /**
  const std::function<void()> fun4 = [*this]() -> void
  {
    //  *this 传值调用
    std::cout << "fun4()..." << std::endl;
    // a++; // error: increment of member 'Test::a' in read-only object
    // num++;
    // std::cout << "num : " << num << std::endl;
  };
  */
};
void fun1();
int main(void)
{
  Test t1;
  // mutable int x = 0; // non-member 'x' cannot be declared 'mutable'
  // auto fun = []() -> void
  // {
  //   std::cout << "fun()..." << std::endl;
  // };
  // fun();
  t1.fun2();
  t1.fun3();
  // t1.fun4();

  int i = 0;
  // auto fun = [i]() mutable -> int
  // {
  //   return ++i;
  // };
  auto fun = [i]() mutable
  {
    return ++i;
  };
  // auto fun = [i](){
  //   static auto a = i;
  //   return ++a;
  // };
  std::cout << fun() << std::endl; // 1
  std::cout << fun() << std::endl; // 2
  std::cout << fun() << std::endl; // 3
  std::cout << "i: " << i << std::endl;
  printf("-------------------end---------------------\n");
  return 0;
}
